package com.woniuxy.shiro.realm;

import com.woniuxy.shiro.entity.Perm;
import com.woniuxy.shiro.entity.Role;
import com.woniuxy.shiro.entity.User;
import com.woniuxy.shiro.service.UserService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashSet;
import java.util.Set;

/**
 * AuthorizingRealm 授权realm
 */
public class CustomRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService; //注入service对象

    private static final Logger logger = LoggerFactory.getLogger(CustomRealm.class);
    /**
     * 获取权限信息
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        logger.info("获取授权信息(角色、权限)");
        //获取账号信息
        String account = (String) principals.getPrimaryPrincipal();
        //以账号作为查询条件查询出当前用户的所有角色    权限管理系统一般都存在一个账号多个角色情况
        User user = userService.findUserAndRolesByAccount(account);
        //打印用户信息
        logger.info(user.toString());

        //模拟从数据库中获取到了当前用户的角色信息
        Set<String> roles = new HashSet<>();
        Set<String> perms = new HashSet<>();
        //遍历获取角色、权限信息
        for (Role role : user.getRoles()) {
            roles.add(role.getName());
            for(Perm perm:role.getPerms()){
                perms.add(perm.getName());
            }
        }
//        roles.add("admin");
//        roles.add("teacher");
//        roles.add("student");

        //假设从数据库中获取到了权限信息
        //perms.add("teacher:add");
//        perms.add("teacher:del");
//        perms.add("teacher:update");
//        perms.add("teacher:find");

        //封装角色信息
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);
        //封装权限信息
        info.setStringPermissions(perms);
        //
        return info;//返回给securityManger（subject）
    }

    /**
     * 获取认证信息
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //token中包含了账号密码信息
        logger.info("调用realm的获取认证信息方法，得到对应用户的账号信息");
        //获取账号、密码信息
        String account = (String) token.getPrincipal();
        String pwd = new String((char[])token.getCredentials());
        logger.info(account+","+pwd);

        //通过账号作为查询条件去数据库中查出对应的账号密码信息  调用service相关方法
        //模拟假设获得了账号密码
        //User user = new User().setAccount("zhangsan").setPwd("f391b473a0240b477164108ee71e68f8");

        User user = userService.findUserByAccount(account);
        if (user==null){
            return null; //报账号不存在异常
        }
        //将查询到的结果封装到AuthenticationInfo中返回给securitymanager，securitymanager会根据
        //AuthenticationInfo中的信息与token中的信息做比对  判断账号密码是否正确
        //参数1：查询到的账号
        //参数2：查询到的密码
        //参数3：当前realm的名字
        SimpleAuthenticationInfo info =
                new SimpleAuthenticationInfo(user.getAccount(),user.getPwd(),this.getName());
        return info;
    }
}
